# cos_uploader.py
import configparser
import os
import logging
from qcloud_cos import CosConfig, CosS3Client
from typing import Dict, Optional

logger = logging.getLogger('CosUploader')


class CosUploader:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(CosUploader, cls).__new__(cls)
            cls._instance._init_client()
        return cls._instance

    def _init_client(self):
        """从 config.ini 初始化COS客户端"""
        try:
            # 读取配置文件
            config = configparser.ConfigParser()
            try:
                with open('config.ini', 'r', encoding='utf-8') as f:
                    config.read_file(f)
            except UnicodeDecodeError:
                logger.error(f"读取配置文件失败")

            # 检查是否存在 COS 配置节
            if 'cos' not in config:
                raise ValueError("配置文件缺少 [COS] 节")

            # 获取配置项（提供默认值或抛出错误）
            cos_config = config['cos']
            secret_id = cos_config.get('secret_id')
            secret_key = cos_config.get('secret_key')
            region = cos_config.get('region')
            bucket = cos_config.get('bucket')

            # 验证必要配置是否存在
            if not all([secret_id, secret_key, region, bucket]):
                raise ValueError("COS 配置项缺失（需要 SecretId/SecretKey/Region/Bucket）")

            # 创建 COS 配置
            cos_client_config = CosConfig(
                Region=region,
                SecretId=secret_id,
                SecretKey=secret_key,
                Token=None,
                Scheme='https'
            )

            # 创建客户端实例
            self.client = CosS3Client(cos_client_config)
            self.bucket = bucket
            self.part_size = 10  # MB
            self.max_thread = 10

            logger.info("COS客户端初始化成功")
        except (ImportError, configparser.Error, ValueError) as e:
            logger.error(f"配置读取失败: {str(e)}")
            self.client = None
        except Exception as e:
            logger.error(f"初始化COS客户端失败: {str(e)}")
            self.client = None

    def upload_file(self, local_file_path: str, cos_key: str) -> Dict:
        """
        上传文件到腾讯云COS

        :param local_file_path: 本地文件路径
        :param cos_key: 在COS中存储的路径（Key）
        :return: 上传结果字典
        """
        if not self.client:
            return {
                'status': 'error',
                'error': 'COS client not initialized',
                'local_path': local_file_path,
                'key': cos_key
            }

        try:
            # 验证文件是否存在
            if not os.path.isfile(local_file_path):
                raise FileNotFoundError(f"本地文件不存在: {local_file_path}")

            # 调用上传接口
            response = self.client.upload_file(
                Bucket=self.bucket,
                LocalFilePath=local_file_path,
                Key=cos_key,
                PartSize=self.part_size * 1024 * 1024,
                MAXThread=self.max_thread,
                EnableMD5=False
            )

            # 获取成功信息
            file_size = os.path.getsize(local_file_path)
            logger.info(
                f"文件上传成功: {local_file_path} → cos://{self.bucket}/{cos_key} "
                f"({file_size // 1024}KB, ETag: {response['ETag']})"
            )

            return {
                'status': 'success',
                'bucket': self.bucket,
                'key': cos_key,
                'etag': response['ETag'],
                'local_path': local_file_path,
                'file_size': file_size
            }
        except Exception as e:
            error_msg = f"上传失败: {local_file_path} → {cos_key}. 错误: {str(e)}"
            logger.error(error_msg)
            return {
                'status': 'error',
                'error': str(e),
                'local_path': local_file_path,
                'key': cos_key
            }
